use strict;
use warnings;

use Tk;
use Tk::WorldCanvas;
use Tk::LabEntry;

use Physics::Springs::Friction;

my $spring_start = undef;	
my $size         =   8;
my $paused       =   1;
my $mass         =   5;
my $k            =   6;
my $sim = Physics::Springs::Friction->new();
$sim->add_friction('stokes', 10);
$sim->add_friction('$F->[1]-=9.8;',);


use Data::Dumper;

my $mw           = MainWindow->new();
my $menu_bar     = $mw->Frame(-relief => 'groove', -borderwidth =>1
                             )->pack(-side=>'top', -fill => 'x');
my $display_area = $mw->Frame()->pack(-side=>'top',-fill=>'x');
my $worldcanvas  = $display_area->WorldCanvas(-width=>400,-height=>400);
							 
$menu_bar->Button(-text=>'Start', -command => sub { $paused = 0; })->pack(-side=>'left');
$menu_bar->Button(-text=>'Pause')->pack(-side=>'left');
$menu_bar->Button(-text    => 'Reset',
				  -command => sub { $sim->clear_particles;
									$sim->{_PhSprings_springs} = [];
									$sim->{FFORCES} = [];
									$spring_start = undef;
									$worldcanvas->delete('all'); },

				 )->pack(-side=>'left');
$menu_bar->LabEntry(-label=>'Mass'    , -textvariable=>\$mass)->pack(-side=>'left');
$menu_bar->LabEntry(-label=>'Sprink K', -textvariable=>\$k)->pack(-side=>'left');


my $i = 1;
$worldcanvas->configure(-bandColor => 'purple');
$worldcanvas->CanvasBind('<3>'               => sub {$worldcanvas->CanvasFocus;
													 $worldcanvas->rubberBand(0)
													});

my $s_start; 
$worldcanvas->CanvasBind('<1>' =>
	sub {
	    # restore old nodes back to previous selection
		$worldcanvas->itemconfigure('selected',-width=>1);
		$worldcanvas->dtag('selected');
		
		$worldcanvas->addtag('selected', withtag=>'current');
		my @tags = $worldcanvas->itemcget('selected', '-tags');
		my $temp;  #temp spot to sitck new selection
		for (@tags) {
			if( $_ =~ /node_(\d+)/) {
			   $temp = $1 
			}
		}
		if (defined $temp) {
			print "Selected '$temp'\n";
			#we just selected something.
			if (!defined $s_start) {
				$s_start = $temp;
			} else {
				$sim->add_spring(k=>$k,p1=>$s_start, p2=>$temp, l=>undef) unless $temp == $s_start;
				$s_start = $temp;
			}
		} else {
			$s_start = undef;
		}
		$worldcanvas->itemconfigure('selected',-width=>3);
		$worldcanvas->raise('node');
		
	}
);
$worldcanvas->CanvasBind('<2>' =>
	sub {
		my ($x,$y) = $worldcanvas->eventLocation;
		
		my $spring_end = $sim->add_particle( x=> $x, y=> $y, z=>0, xv => 1, yv => 0, m=>$mass);
		my $name = "node_" . $spring_end;
		$worldcanvas->createOval( $x-$size,$y-$size,$x+$size,$y+$size, -fill=>'red', -tag=> ['node',$name]);
		print "Inserting at $name ($x,$y)\n";
		
		#$worldcanvas->update();
		$worldcanvas->raise('node');
		$spring_start = $spring_end;
	}
);

$worldcanvas->CanvasBind('<3>' =>
	sub {
		my ($x,$y) = $worldcanvas->eventLocation;
		
		my $spring_end = $sim->add_particle( x=> $x, y=> $y, z=>0, xv => 1, yv => 0, m=>10_000_000);
		my $name = "node_" . $spring_end;
		$worldcanvas->createOval( $x-$size,$y-$size,$x+$size,$y+$size, -fill=>'yellow', -tag=> ['node',$name]);
		print "Inserting at $name ($x,$y)\n";
		
		#$worldcanvas->update();
		$worldcanvas->raise('node');
		$spring_start = $spring_end;
	}
);

$worldcanvas->CanvasBind('<Up>' => sub {$worldcanvas->rubberBand(1);});
$worldcanvas->CanvasBind('<Down>' => sub {$worldcanvas->rubberBand(1);});
$worldcanvas->CanvasBind('<Left>' => sub {$worldcanvas->rubberBand(1);});
$worldcanvas->CanvasBind('<Right>' => sub {$worldcanvas->rubberBand(1);});
$worldcanvas->CanvasBind('<i>' => sub {$worldcanvas->zoom(1.25); $worldcanvas->rubberBand(1);});
$worldcanvas->CanvasBind('<o>' => sub {$worldcanvas->zoom(0.8);  $worldcanvas->rubberBand(1);});
$worldcanvas->pack();
$worldcanvas->CanvasFocus;
$worldcanvas->repeat(100, 
		sub {
			$sim->iterate_step(2) unless $paused;
			foreach my $i (0.. scalar @{ $sim->{p} }-1) {
				my $p = $sim->{p}[$i];
				$worldcanvas->coords("node_$i",  $p->{x} - $size , $p->{y} - $size, $p->{x} + $size , $p->{y} + $size );
			}
			foreach my $spring (@{$sim->{_PhSprings_springs}}) {
				my $p1 = $sim->{p}[$spring->{p1}];
				my $p2 = $sim->{p}[$spring->{p2}];
				my $spring_name = 'spring_' . $spring;
				if ($worldcanvas->find('withtag',$spring_name)) {
					$worldcanvas->coords($spring_name, $p1->{x}, $p1->{y}, $p2->{x}, $p2->{y});
					#print "$spring_name ", $spring->{strech}, "\n";
				} else {
					$worldcanvas->createLine($p1->{x}, $p1->{y}, $p2->{x}, $p2->{y}, -tag=>$spring_name);
				}
			}		
				
		});
		

MainLoop;
